package ca.jsbr.canvaswar.games.map 
{
	import ca.jsbr.as2js_lib.display.canvas.Node2D;
	import ca.jsbr.as2js_lib.display.canvas.view.SpriteView;
	import ca.jsbr.as2js_lib.utils.geom.Point;
	import ca.jsbr.as2js_lib.utils.grid.Astar;
	import ca.jsbr.canvaswar.games.unit.Unit;
	/**
	 * ...
	 * @author jsbr [jsricard@lvlstudio.com]
	 */
	public class Map extends Node2D 
	{
		private var _description:MapDescription;
		private var _tiles:Vector.<Tile>;
		private var _analyse:Vector.<Tile>;
		private var _aStar:Astar;
		
		public function Map(description:MapDescription) 
		{
			_description = description;
			_tiles = new Vector.<Tile>();
			_aStar = new Astar();
		}
		
		public function generate(w:int=-1,h:int=-1):void
		{
			
			var asset:SpriteView = _description.asset;
			asset.name = "map1";
			if (width == -1)
				_w = (_description.width / asset.width >> 0) + 1;
			else
				_w = (w / asset.width >> 0) + 1;
				
			if (height == -1)
				_h = (_description.height / asset.height >> 0) + 1;
			else
				_h = (h / asset.height >> 0) + 1;

			for (var i:int = 0; i < _h * _w; i++)
			{
				var tx:int = i % _w;
				var ty:int = (i / _w) >> 0;
				var tile:Tile = new Tile(tx,ty,asset.clone());
				tile.asset.x = tx * asset.width;
				tile.asset.y = ty * asset.height;
				tile.asset.stop();
				tile.asset.gotoFrame(0);
				_tiles.push(tile);
				addChild(tile.asset);
			}
			_aStar.setTiles(_tiles, new Point(_w, _h));
		}
		
		
		public function getTile(x:int,y:int):Tile
		{
			return _tiles[x + y * _w];
		}
		
		public function getTileByCoordinate(x:int,y:int):Tile
		{
			var tx:int = Math.floor(x / _description.asset.width);
			var ty:int = Math.floor(y / _description.asset.height);
			return getTile(tx, ty);
		}
		
		public function addUnit(unit:Unit):void
		{
			unit.asset.x = unit.position.x * _description.asset.width;
			unit.asset.y = unit.position.y * _description.asset.height;
			if (unit.asset.height > _description.asset.height) {
				unit.offset.y = _description.asset.height - unit.asset.height - 1;
				unit.asset.y += unit.offset.y;
			}
			var tile:Tile = getTile(unit.position.x, unit.position.y);
			tile.unit = unit;
			unit.tile = tile;
			addChild(unit.asset);
		}
		
		public function showTileMove(unit:Unit, moveAsset:SpriteView, attackAsset:SpriteView):Vector.<Tile>
		{
			var move:int = unit.move;
			clearOverlay();
			_analyse = new Vector.<Tile>();
			var tiles:Vector.<Tile> = checkAround(move, unit.tile);
			var o:SpriteView;
			for (var i:int = 0; i < tiles.length; i++)
			{
				if (tiles[i].overlay)
					tiles[i].overlay.parent.removeChild(tiles[i].overlay);
				if (tiles[i].unit)
				{
					var unit2:Unit = tiles[i].unit;
					if (unit2.faction == unit.faction)
						continue;
					else
						o = attackAsset.clone();
				}
				else
					o = moveAsset.clone();
				tiles[i].overlay = o;
				if (tiles[i].unit)
				{
					addChild(tiles[i].unit.asset);
				}
				o.x = tiles[i].position.x * _description.asset.width;
				o.y = tiles[i].position.y * _description.asset.height;
				addChild(o);
			}
			addChild(unit.asset);
			return tiles;
		}
		
		public function clearOverlay():void
		{
			if (_analyse)
			{
				for (var i:int = 0; i < _analyse.length; i++)
				{
					if (_analyse[i].overlay)
					{
						_analyse[i].overlay.parent.removeChild(_analyse[i].overlay);
						_analyse[i].overlay = null;
					}
				}
			}
		}
		
		public function getPath(start:Tile, end:Tile):Vector.<Tile>
		{
			return _aStar.findPath(start, end);
		}
		
		private function checkAround(cost:int, tile:Tile):Vector.<Tile>
		{
			
			var ret:Vector.<Tile> = new Vector.<Tile>();
			if (cost < 0)
				return ret;
			if (cost == 0 && !tile.unit)
				return ret;
			ret.push(tile);
			_analyse.push(tile);
			var arr:Array = [0, 1, 1, 0, -1, 0, 0, -1];
			
			for (var i = 0; i < 8; i++)
			{
				tile2 = getTile(tile.position.x + arr[i], tile.position.y +arr[++i]);
				if (tile2 && tile2.moveCost <= cost && _analyse.indexOf(tile2)==-1)
					ret = ret.concat(checkAround(cost - tile2.moveCost, tile2));
			}
				
			
			return ret;
		}
		
		public function get description():MapDescription 
		{
			return _description;
		}
		
	}

}